home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / zansi_10.arc / ZANSI_P.ASM < prev    next >
Assembly Source File  |  1987-12-18  |  12KB  |  301 lines

  1. ;----- zansi_p.asm --------------------------------------------------------
  2. ; Zephyr ANSI terminal driver.
  3. ;    Copyright (C) 1986, Thomas Hanlin III, Springfield VA.
  4. ;    Based on original code for NANSI by Daniel Kegel, Pasadena, CA.
  5. ;------------------------------------------------------------------------
  6. ; A state machine implementation of the mechanics of ANSI terminal control
  7. ; string parsing.
  8. ;
  9. ; Entered with a jump to f_escape when driver finds an escape, or
  10. ; to f_in_escape when the last string written to this device ended in the
  11. ; middle of an escape sequence.
  12. ;
  13. ; Exits by jumping to f_ANSI_exit when an escape sequence ends, or
  14. ; to f_not_ANSI when a bad escape sequence is found, or (after saving state)
  15. ; to f_loopdone when the write ends in the middle of an escape sequence.
  16. ;
  17. ; Parameters are stored as bytes in param_buffer.  If a parameter is
  18. ; omitted, it is stored as zero.  Each character in a keyboard reassignment
  19. ; command counts as one parameter.
  20. ;
  21. ; When a complete escape sequence has been parsed, the address of the
  22. ; ANSI routine to call is found in ansi_fn_table.
  23. ;
  24. ; Register usage during parsing:
  25. ;  DS:SI points to the incoming string.
  26. ;  CX holds the length remaining in the incoming string.
  27. ;  ES:DI points to the current location on the memory-mapped screen.
  28. ;  DX is number of characters remaining on the current screen line.
  29. ;  BX points to the current paramter byte being assembled from the incoming
  30. ;  string.  (Stored in cur_parm_ptr between device driver calls, if needed.)
  31. ;
  32. ; The registers are set as follows before calling the ANSI subroutine:
  33. ;  AX = max(1, value of first parameter)
  34. ;  CX = number of paramters
  35. ;  SI = offset of second parameter from CS
  36. ;  DS = CS
  37. ;  ES:DI points to the current location on the memory-mapped screen.
  38. ;  DX is number of characters remaining on the current screen line.
  39. ; The subroutine is free to trash AX, BX, CX, SI, and DS.
  40. ; It must preserve ES, and can alter DX and DI if it wants to move the
  41. ; cursor.
  42. ;
  43. ;------------------------------------------------------------------------
  44.  
  45.         ; From zansi.asm
  46.         extrn   f_not_ANSI:near         ; exit: abort bad ANSI cmd
  47.         extrn   f_ANSI_exit:near        ; exit: good cmd done
  48.         extrn   f_loopdone:near         ; exit: ran out of chars. State saved.
  49.         extrn   escvector:word          ; saved state: where to jump
  50.         extrn   cur_parm_ptr:word       ; saved state: where to put next param
  51.         extrn   string_term:byte        ; saved state: what ends string
  52.         extrn   cur_x:byte, max_x:byte  ; 0 <= cur_x <= max_x
  53.         extrn   cur_attrib:byte         ; current color/attribute
  54.  
  55.         ; from zansi_f.asm
  56.         extrn   ansi_fn_table:word      ; ANSI subroutine table
  57.  
  58.         ; Used in zansi.asm
  59.         public  f_escape                ; entry: found an escape
  60.         public  f_in_escape             ; entry: restore state, keep parsing
  61.  
  62.         ; Used in zansi_i.asm and zansi_f.asm
  63.         public  param_buffer, param_end, redef_end
  64.  
  65.  
  66. code    segment byte public 'CODE'
  67.         assume  cs:code
  68.  
  69. ; More saved state
  70. in_num          db      ?       ; true if between a digit and a semi in parse
  71.  
  72. param_buffer    dw      3000h   ; address of first byte free for new params
  73. param_end       dw      3030h   ; address of end of free area
  74. redef_end       dw      3030h   ; address of end of redefinition area
  75.                 ; These initialized values are only for debugging
  76.  
  77. ;----- next_is -------------------------------------------------------
  78. ; Next_is is used to advance to the next state.  If there are characters
  79. ; left in the input string, we jump immediately to the new state;
  80. ; otherwise, we shut down the recognizer, and wait for the next call
  81. ; to the device driver.
  82. next_is macro   statename
  83.         loop    statename
  84.         mov     ax, offset statename
  85.         jmp     sleep
  86.         endm
  87.  
  88. ;----- sleep --------------------------------------------------------
  89. ; Remember bx and next state, then jump to device driver exit routine.
  90. ; Device driver will re-enter at f_in_escape upon next invocation
  91. ; because escvector is nonzero; parsing will then be resumed.
  92. sleep:  mov     cs:cur_parm_ptr, bx
  93.         mov     cs:escvector, ax
  94.         jmp     f_loopdone
  95.  
  96. ;----- f_in_escape ---------------------------------------------------
  97. ; Main loop noticed that escvector was not zero.
  98. ; Recall value of BX saved when sleep was jumped to, and jump into parser.
  99. f_in_escape:
  100.         mov     bx, cs:cur_parm_ptr
  101.         jmp     word ptr cs:escvector
  102.  
  103. fbr_syntax_error_gate:          ; jumped to from inside f_bracket
  104.         jmp     syntax_error
  105.  
  106. ;----- f_escape ------------------------------------------------------
  107. ; We found an escape.  Next character should be a left bracket.
  108. f_escape:
  109.         next_is f_bracket
  110.  
  111. ;----- f_bracket -----------------------------------------------------
  112. ; Last char was an escape.  This one should be a [; if not, print it.
  113. ; Next char should begin a parameter string.
  114. f_bracket:
  115.         lodsb
  116.         cmp     al, '['
  117.         jnz     fbr_syntax_error_gate
  118.         ; Set up for getting a parameter string.
  119.         mov     bx, cs:param_buffer
  120.         mov     byte ptr cs:[bx], 0
  121.         mov     cs:in_num, 0
  122.         next_is f_get_args
  123.  
  124. ;----- f_get_args ---------------------------------------------------
  125. ; Last char was a [.  If the current char is a '=' or a '?', eat it.
  126. ; In any case, proceed to f_get_param.
  127. ; This is only here to strip off the strange chars that follow [ in
  128. ; the SET/RESET MODE escape sequence.
  129. f_get_args:
  130.         lodsb
  131.         cmp     al, '='
  132.         jz      fga_ignore
  133.         cmp     al, '?'
  134.         jz      fga_ignore
  135.                 dec     si              ; let f_get_param fetch al again
  136.                 jmp     short f_get_param
  137. fga_ignore:
  138.         next_is f_get_param
  139.  
  140. ;----- f_get_param ---------------------------------------------------
  141. ; Last char was one of the four characters "]?=;".
  142. ; We are getting the first digit of a parameter, a quoted string,
  143. ; a ;, or a command.
  144. f_get_param:
  145.         lodsb
  146.         cmp     al, '0'
  147.         jb      fgp_may_quote
  148.         cmp     al, '9'
  149.         ja      fgp_may_quote
  150.                 ; It's the first digit.  Initialize current parameter with it.
  151.                 sub     al, '0'
  152.                 mov     byte ptr cs:[bx], al
  153.                 mov     cs:in_num, 1    ; set flag for sensing at cmd exec
  154.                 next_is f_in_param
  155. fgp_may_quote:
  156.         cmp     al, '"'
  157.         jz      fgp_isquote
  158.         cmp     al, "'"
  159.         jnz     fgp_semi_or_cmd         ; jump to code shared with f_in_param
  160. fgp_isquote:
  161.         mov     cs:string_term, al      ; save it for end of string
  162.         next_is f_get_string            ; and read string into param_buffer
  163.  
  164. ;----- f_get_string -------------------------------------
  165. ; Last character was a quote or a string element.
  166. ; Get characters until ending quote found.
  167. f_get_string:
  168.         lodsb
  169.         cmp     al, cs:string_term
  170.         jz      fgs_init_next_param
  171.         mov     byte ptr cs:[bx], al
  172.         cmp     bx, cs:param_end
  173.         adc     bx, 0                   ; if bx<param_end bx++;
  174.         next_is f_get_string
  175. ; Ending quote was found.
  176. fgs_init_next_param:
  177.         mov     byte ptr cs:[bx], 0     ; initialize new parameter
  178.         ; | Eat following semicolon, if any.
  179.         next_is f_eat_semi
  180.  
  181. ;----- f_eat_semi -------------------------------------
  182. ; Last character was an ending quote.
  183. ; If this char is a semi, eat it; else unget it.
  184. ; Next state is always f_get_param.
  185. f_eat_semi:
  186.         lodsb
  187.         cmp     al, ';'
  188.         jz      fes_eaten
  189.         inc     cx
  190.         dec     si
  191. fes_eaten:
  192.         next_is f_get_param
  193.  
  194. ;----- syntax_error ---------------------------------------
  195. ; A character was rejected by the state machine.  Exit to
  196. ; main loop, and print offending character.  Let main loop
  197. ; decrement CX (length of input string).
  198. syntax_error:
  199.         mov     cs:escvector, 0
  200.         mov     ah, cs:cur_attrib
  201.         jmp     f_not_ANSI      ; exit, print offending char
  202.  
  203. ;------ f_in_param -------------------------------------
  204. ; Last character was a digit.
  205. ; Looking for more digits, a semicolon, or a command character.
  206. f_in_param:
  207.         lodsb
  208.         cmp     al, '0'
  209.         jb      fgp_semi_or_cmd
  210.         cmp     al, '9'
  211.         ja      fgp_semi_or_cmd
  212.         ; It's another digit.  Add into current parameter.
  213.         sub     al, '0'
  214.         xchg    byte ptr cs:[bx], al
  215.         push    dx
  216.         mov     dl, 10
  217.         mul     dl
  218.         pop     dx
  219.         add     byte ptr cs:[bx], al
  220.         next_is f_in_param
  221.         ; Code common to states get_param and in_param.
  222.         ; Accepts a semicolon or a command letter.
  223. fgp_semi_or_cmd:
  224.         cmp     al, ';'
  225.         jnz     fgp_not_semi
  226.         cmp     bx, cs:param_end        ; prepare for next param-
  227.         adc     bx, 0                   ; if bp<param_end bp++;
  228.         ; Set new param to zero, enter state f_get_param.
  229.         mov     cs:in_num, 0            ; no longer inside number
  230.         jmp     fgs_init_next_param     ; spaghetti code attack!
  231. fgp_not_semi:
  232.         ; It must be a command letter.
  233.         cmp     al, '@'
  234.         jb      syntax_error
  235.         cmp     al, 'z'
  236.         ja      syntax_error
  237.         cmp     al, 'Z'
  238.         jbe     fgp_is_cmd
  239.         cmp     al, 'a'
  240.         jb      syntax_error
  241.         ; It's a lower-case command letter.
  242.         ; Remove hole between Z and a to save space in table.
  243.         sub     al, 'a'-'['
  244. fgp_is_cmd:
  245.         ; It's a command letter.  Save registers, convert letter
  246.         ; into address of routine, set up new register usage, call routine.
  247.         push    si                      ; These three registers hold info
  248.         push    cx                      ; having to do with the input string,
  249.         push    ds                      ; which has no interest at all to the
  250.                                         ; control routine.
  251.  
  252.         push    cs
  253.         pop     ds                      ; ds is now cs
  254.  
  255.         sub     al, '@'                 ; first command is @: insert chars
  256.         cbw
  257.         shl     ax,1
  258.         add     ax, offset ansi_fn_table
  259.         ; ax is now pointer to command routine address in table
  260.  
  261.         mov     cx, bx
  262.         mov     si, param_buffer        ; si is now pointer to parameters
  263.         sub     cx, si                  ;
  264.         test    in_num, 1
  265.         jz      fip_out_num
  266.         inc     cx
  267. fip_out_num:                            ; cx is now # of parameters
  268.  
  269.         mov     bx,ax                   ; save pointer to routine in bx
  270.  
  271.         ; Calculate cur_x from DX.
  272.         mov     al, max_x
  273.         inc     ax
  274.         sub     al, dl
  275.         mov     cur_x, al
  276.  
  277.         ; Get first parameter into AX; if defaulted, set it to 1.
  278.         xor     ah,ah
  279.         lodsb
  280.         or      al, al
  281.         jnz     fgp_callem
  282.         inc     ax
  283. fgp_callem:
  284.         ; Finally, call the command subroutine.
  285.         call    word ptr [bx]
  286.  
  287.         pop     ds
  288.         pop     cx
  289.         pop     si
  290.  
  291.         mov     ah, cs:cur_attrib       ; Prepare for STOSW.
  292.         mov     cs:escvector, 0         ; No longer parsing escape sequence.
  293.         ; Set flags for reentry at loopnz
  294.         or      dx, dx                  ; "Any columns left on line?"
  295.         ; Re-enter at bottom of main loop.
  296.         jmp     f_ansi_exit
  297.  
  298.  
  299. code    ends
  300.         end
  301.